/**
  ******************************************************************************
  * @file           : pid.h
  * @author         : Mark Xiang
  * @brief          : PID controller
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */
#ifndef __PID_H
#define __PID_H

/* ------------------------------ Includes ------------------------------ */

/* ------------------------------ Defines ------------------------------ */

/* ------------------------------ Enum Typedef ------------------------------ */

/* ------------------------------ Struct Typedef ------------------------------ */
typedef struct
{
  /* coefficients & parameters to be read from flash */
  float kp, ki, kd;
  float A, B, C;
  float output_increment_limit, output_limit;
  // float feedforward_gain;
  // @todo feedforward

  /* working variables */
  float target;
  float feedback;
  float err;
  float err_last1;
  float err_last2;

  /* output */
  float output_increment;
  float output;
}Pid_t;
/* ------------------------------ Variable Declarations ------------------------------ */

/* ------------------------------ Manager Typedef ------------------------------ */
typedef struct
{
/**
  * @brief  Initiate pid struct.
  * @param  pid pointer to pid struct
  * @param  kp kp
  * @param  ki ki
  * @param  kd kd
  * @param  output_limit limit of output of pid controller, no limit if set as 0
  * @param  output_increment_limit limit of output increment of pid controller, no limit if set as 0
  * @retval None
  */
  void (*Init)(Pid_t *pid, float kp, float ki, float kd, float output_limit, float output_increment_limit);

/**
  * @brief  Change kp.
  * @param  pid pointer to pid struct
  * @param  kp new kp
  * @retval None
  */
  void (*ResetKp)(Pid_t *pid, float kp);

/**
  * @brief  Change ki.
  * @param  pid pointer to pid struct
  * @param  ki new ki
  * @retval None
  */
  void (*ResetKi)(Pid_t *pid, float ki);

/**
  * @brief  Change kd.
  * @param  pid pointer to pid struct
  * @param  kd new kd
  * @retval None
  */
  void (*ResetKd)(Pid_t *pid, float kd);

/**
  * @brief  Set target of pid controller.
  * @param  pid pointer to pid struct
  * @param  target target of pid controller
  * @retval None
  */
  void (*SetTarget)(Pid_t *pid, float target);

/**
  * @brief  Do pid calculation.
  * @param  pid pointer to pid struct
  * @param  feedback feedback to pid controller
  * @retval output of pid controller
  */
  float (*DoPidCalc)(Pid_t *pid, float feedback);
}PidManager_typedef;
/* ------------------------------ Manager Extern ------------------------------ */
extern const PidManager_typedef Pid;


#endif

